//This should draw blocks

#include <cstdlib>
#include <stdio.h>
#include <string>
#include <fstream>
#include <iostream>
#include <cmath>
#include <GL/glut.h>

#include "SOIL.h"
#include "blockManager.h"

using namespace std;

#define PI 3.14159

float centerX = 0.0;
float centerY = 0.0;
float ballX = 0.0;
float ballY = 0.0;
float aimAngle = 60;
float speed = .015;
bool ballMoving = false;
float prevY, prevX;

int width = 5, depth = 4;
float innerDim = ((float)(3*width - depth))/2;

blockManager bMan(width, depth);

GLuint brickBlue, brickRed, brickGreen, brickYellow;

void drawBall(int numPts, float size, float xcenter, float ycenter){
	glBegin(GL_POLYGON);
		for (int i=0; i<numPts; i++){
			float angle = (2*PI*i)/numPts;
			if(angle < 2*PI && angle > 0){
				glVertex2f(xcenter+size*cos(angle), ycenter+size*sin(angle));
			}
		}
	glEnd();
}
void buildBlocks(){
	glEnable(GL_TEXTURE_2D);
	
	glColor3ub(255,255,255);
	float bX, bY;

	for(int i = 0; i < (4*depth*width); i++){
		if(bMan.exists(i)){
			bX = bMan.x(i)+centerX;
			bY = bMan.y(i)+centerY;
			switch(bMan.side(i)){
				case TOP:
					glBindTexture(GL_TEXTURE_2D, brickRed);
					break;
				case RIGHT:
					glBindTexture(GL_TEXTURE_2D, brickYellow);
					break;
				case BOTTOM:
					glBindTexture(GL_TEXTURE_2D, brickGreen);
					break;
				case LEFT:
					glBindTexture(GL_TEXTURE_2D, brickBlue);
					break;
			}
			if(bMan.orientation(i) == VERTICAL){ 
				glBegin(GL_QUADS);
					glTexCoord2d(1,1); glVertex3f(bX+.5, bY+1.5, 0);
					glTexCoord2d(0,1); glVertex3f(bX-.5, bY+1.5, 0);
					glTexCoord2d(0,0); glVertex3f(bX-.5, bY-1.5, 0);
					glTexCoord2d(1,0); glVertex3f(bX+.5, bY-1.5, 0);
				glEnd();
			}
			else{
				glBegin(GL_QUADS);
					glTexCoord2d(1,1); glVertex3f(bX+1.5, bY+.5, 0);
					glTexCoord2d(0,1); glVertex3f(bX-1.5, bY+.5, 0);
					glTexCoord2d(0,0); glVertex3f(bX-1.5, bY-.5, 0);
					glTexCoord2d(1,0); glVertex3f(bX+1.5, bY-.5, 0);
				glEnd();
			}
		}
	}
	glDisable(GL_TEXTURE_2D);
}
void display(){
	glClear(GL_COLOR_BUFFER_BIT);
	
	buildBlocks();
	drawBall(50,.25,ballX,ballY);

	glutSwapBuffers();

}
void keys(unsigned char key, int mx, int my){		
	switch (key){
		case 'q':
		case 'Q':
			exit(0);
		case ' ':
			ballMoving = !ballMoving;
	}
}
void specKeys(int key, int mx, int my){
	switch (key){
		case GLUT_KEY_UP:
			centerY += 0.2;
			glutPostRedisplay();
			break;
		case GLUT_KEY_DOWN:
			centerY -= 0.2;
			glutPostRedisplay();
			break;
		case GLUT_KEY_LEFT:
			centerX -= 0.2;
			glutPostRedisplay();
			break;
		case GLUT_KEY_RIGHT:
			centerX += 0.2;
			glutPostRedisplay();
			break;
		case GLUT_KEY_HOME:
			centerX = 0.0;
			centerY = 0.0;
			glutPostRedisplay();
			break;
	}
}
void timerStuff(int increment){
	if(ballMoving){
		vector<int> info(2);
		float distX = (ballX-centerX);
		float distY = (ballY-centerY);

		if((fabs(distX) > (innerDim) && fabs(distX) < (innerDim+depth)) || (fabs(distY) > (innerDim) && fabs(distY) < (innerDim + depth))){
			info = bMan.getInfo(distX, distY);
			if(bMan.exists(info[0])){
				if(info[1] == TOP || info[1] == BOTTOM){
					aimAngle = 360-aimAngle;
				}
				else{
					if(aimAngle >= 180 && aimAngle <= 360)
						aimAngle = 540 - aimAngle;
					else
						aimAngle = 180 - aimAngle;
				}
				bMan.destroy(info[0]);
			}
		}
		ballX += cos((aimAngle/180)*PI)*speed;
		ballY += sin((aimAngle/180)*PI)*speed;
	}
	glutTimerFunc(1,timerStuff,increment); // do it again
	glutPostRedisplay();	
}
void initTextures(){
	brickBlue = SOIL_load_OGL_texture("brick_blue.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
	brickGreen = SOIL_load_OGL_texture("brick_green.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
	brickRed = SOIL_load_OGL_texture("brick_red.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
	brickYellow = SOIL_load_OGL_texture("brick_yellow.png", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
}
void init(){
	glClearColor (0.0, 0.0, 0.0, 1.0); // set background color to black
	glMatrixMode (GL_PROJECTION); 
	glLoadIdentity ();    
	glOrtho(-16.0, 16.0, -16.0, 16.0, -16.0, 16.0);  
}
int main(int argc, char** argv){
  	glutInit(&argc,argv);

  	glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); // single color buffer    	
  	glutInitWindowSize(500,500); // 500x500 window
  	glutInitWindowPosition(0,0); // anchored at upper left of screen

 	glutCreateWindow("Blocks");  // window with banner "simple"
  	glutDisplayFunc(display);  // register the display callback function
  	glutKeyboardFunc(keys);
  	glutSpecialFunc(specKeys);
  	glutTimerFunc(1,timerStuff,1);
  
  	init(); // perform some initialization steps
  	initTextures();

  	glutMainLoop(); // enter the main event loop

  	return 0;
}

